package com.symaster.common.connect.v2;

import com.alibaba.fastjson.JSONObject;
import com.symaster.common.connect.listener.NodeListener;
import com.symaster.common.connect.local.ConnectObj;
import com.symaster.common.connect.tcp.TcpElementR;
import com.symaster.common.connect.tcp.TcpElementW;
import com.symaster.common.connect.util.ClientCommon;
import com.symaster.common.util.IOUtil;

import java.io.Closeable;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;

/**
 * @author yinmiao
 * @version 2022-05-03 11:28
 */
public class Node extends NodeListener implements Closeable, MasterEnum {

    private final String masterIp;
    private final int masterPort;
    private final int port;
    private ConnectObj connectObj;

    public Node(String masterIp, int masterPort) {
        this.masterIp = masterIp;
        this.masterPort = masterPort;
        this.port = IOUtil.randomPort();
        init();
    }

    public void sendToMaster(String message) {
        try {
            ClientCommon._send(connectObj, message);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public String sendAndWaitToMaster(String message) {
        try {
            return ClientCommon._sendAndWait(connectObj, message);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private void init() {
        connectObj = new ConnectObj();
        connectObj.setIp(masterIp);

        try {
            TcpElementR tcpElementR = new TcpElementR(port);
            tcpElementR.setMessageHandler(message -> {
                JSONObject jsonObject = JSONObject.parseObject(message);
                String s = jsonObject.getString(EXECUTE);
                if (CONNECT_ME.equals(s)) {
                    try {
                        Integer port = jsonObject.getInteger(PORT);
                        TcpElementW tcpElementW = new TcpElementW(masterIp, port);
                        connectObj.setTcpElementW(tcpElementW);
                        connectObj.setPort(port);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                } else {
                    return messageHandler(connectObj, jsonObject.getString(MESSAGE));
                }
                return null;
            });
            connectObj.setTcpElementR(tcpElementR);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        sendToRegistrationCenter();
    }

    private void sendToRegistrationCenter() {

        byte[] portByte = ClientCommon.int2byte(port);
        byte[] bytes = new byte[52];
        bytes[4] = portByte[0];
        bytes[5] = portByte[1];
        bytes[6] = portByte[2];
        bytes[7] = portByte[3];

        DatagramSocket datagramSocket = null;
        try {
            datagramSocket = new DatagramSocket();
            datagramSocket.send(new DatagramPacket(bytes, bytes.length, new InetSocketAddress(masterIp, masterPort)));
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            IOUtil.close(datagramSocket);
        }
    }

    @Override
    public void close() throws IOException {
        IOUtil.close(connectObj);
    }
}
